package com.doyoulike.util;

import cn.hutool.core.util.StrUtil;
import com.doyoulike.config.CusException;
import com.doyoulike.config.gen.GenConfigXMLRoot;
import com.doyoulike.config.gen.GenTemplate;
import com.doyoulike.config.gen.GenType;
import com.doyoulike.enums.GenTypeEnum;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.util.CollectionUtils;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 加载模板列表
 */
public class LoadTemplateTool {

    /**
     * 获取模板列表
     */
    public static List<GenTemplate> loadTemplateList(GenTypeEnum genType) {
        // 一、获取模板的存放路径
        List<String> templatePathList = getTemplatePathListByGenType(genType.getKey());

        // 二、根据路径加载模板
        List<GenTemplate> templates = new ArrayList<>();
        templatePathList.forEach(path -> templates.add(xmlFileToObject(path, GenTemplate.class)));

        // 三、返回模板
        return templates;
    }

    /**
     * 根据生成方式获取对应的模板路径
     */
    private static List<String> getTemplatePathListByGenType(String genType) {
        // 一、将（模板路径）根据（生成类型）分组保存到 Map
        GenConfigXMLRoot xmlRoot = getGenConfigXMLRoot();
        Map<String, List<String>> templatePathMap = xmlRoot.getGenTypeList().stream().collect(Collectors.toMap(GenType::getCode, GenType::getTemplatePathList));

        // 二、根据 genTypeCode（生成类型）获取对应的模板路径
        List<String> result = templatePathMap.get(genType);
        if (CollectionUtils.isEmpty(result)) throw new CusException(StrUtil.format("({})的没有配置模板路径", genType));

        // 三、返回模板路径
        return result;
    }

    /**
     * 获取模板路径配置（读取 gen/gen-template-path.xml 下所有模板文件的路径）
     */
    private static GenConfigXMLRoot getGenConfigXMLRoot() {
        return xmlFileToObject("gen/gen-template-path.xml", GenConfigXMLRoot.class);
    }

    /**
     * 根据路径将 XML文件解析为对象
     */
    @SuppressWarnings("unchecked")
    public static <T> T xmlFileToObject(String filePath, Class<?> clazz){
        try {
            // 读取 resource 目录下的文件
            Resource resource = new ClassPathResource(filePath);

            // 利用输入流获取 XML 文件内容
            InputStream is = resource.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is, "UTF-8"));

            // 将文件内容保存到 StringBuilder
            StringBuilder sb = new StringBuilder();
            while (true) {
                String line = br.readLine();
                if (line == null) break;
                sb.append(line).append("\r\n");
            }

            is.close();
            br.close();

            // 将 XML 解析为指定的对象返回
            return (T) xmlStrToObject(clazz, sb.toString());
        } catch (Exception e) {
            throw new CusException(StrUtil.format("代码生成-加载gen/gen-template-path.xml配置文件时转换失败：{}", e.getMessage()));
        }
    }

    /**
     * 将XML转为指定的POJO对象
     * @param clazz 需要转换的类
     * @param xmlStr xml数据
     */
    public static Object xmlStrToObject(Class<?> clazz, String xmlStr) throws Exception {
        Object xmlObject = null;
        Reader reader = null;

        // 利用JAXBContext将类转为一个实例
        JAXBContext context = JAXBContext.newInstance(clazz);
        // XMl 转为对象的接口
        Unmarshaller unmarshaller = context.createUnmarshaller();
        reader = new StringReader(xmlStr);
        xmlObject = unmarshaller.unmarshal(reader);
        if (reader != null) {
            reader.close();
        }
        return xmlObject;
    }
    /**
     * ========================= 获取模板路径配置 end ===========================
     */

}
